﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;
using System.Globalization;
using Sherwood.SignOn.Server.Models.Repositories;
using Sherwood.SignOn.Server.Models.Services;
using Sherwood.SignOn.Server.Content;

namespace Sherwood.SignOn.Server.Models.ViewModels
{
    /// <summary>
    /// View model for /UserAccount/ChangePassword action
    /// </summary>
    public class ChangePasswordViewModel : ViewModelBase
    {
        public string UserAccountId { get; set; }
        public string VerificationCode { get; set; }
        public string NewPassword1 { get; set; }
        public string NewPassword2 { get; set; }
        public string RequestedUrl { get; set; }
        public string DisplayName { get; set; }

        public string RedirectUrl
        {
            get
            {
                if (!string.IsNullOrEmpty(RequestedUrl))
                    return "/SignIn/?ReturnUrl=" + HttpUtility.UrlEncode(RequestedUrl);
                else
                    return "/SignIn/";
            }
        }

        /// <summary>
        /// Attempts to change a user's password. The user's identity is verified by checking the VerificationCode 
        /// and UserAccountId properties. These would usually be passed as query string parameters along with a request.
        /// </summary>
        /// <param name="state"></param>
        /// <returns></returns>
        public bool ChangePassword(ModelStateDictionary state)
        {
            if (!string.IsNullOrEmpty(UserAccountId) && !string.IsNullOrEmpty(VerificationCode))
            {
                IUserAccount account = Data.UserAccounts.GetUserAccount(new Guid(UserAccountId));
                if (account != null)
                {
                    if (account.ValidateVerificationCode(VerificationCode))
                    {
                        DisplayName = account.DisplayName;
                        if (account.VerificationStatus != VerificationStatus.ResetPassword)
                        {
                            state.AddModelError("", Translations.ChangePassword_No_Change_Request);
                            return false;
                        }
                        else
                        {

                            if (UserAccountHelper.IsWeakPassword(account.UserName, NewPassword1))
                            {
                                //Invalid password
                                if (!string.IsNullOrEmpty(NewPassword1))
                                {
                                    state.AddModelError("NewPassword1", Translations.ChangePassword_Invalid_Password);
                                }
                                return false;
                            }
                            else
                            {
                                if (!NewPassword1.Equals(NewPassword2))
                                {
                                    //Invalid verification code
                                    state.AddModelError("NewPassword1", Translations.ChangePassword_Passwords_Do_Not_Match);
                                    state.AddModelError("NewPassword2", Translations.ChangePassword_Passwords_Do_Not_Match);
                                    return false;
                                }
                                else
                                {
                                    if (account.SetPassword(NewPassword1))
                                    {
                                        RequestedUrl = account.RequestedUrl;
                                        account.SetVerificationParameters(VerificationStatus.Verified, null, null);
                                        return true;
                                    }
                                    else
                                    {
                                        //Error occured trying to set password.
                                        state.AddModelError("", Translations.ChangePassword_Failure);
                                        return false;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        //Invalid verification code
                        state.AddModelError("", Translations.ChangePassword_Failure);
                        return false;
                    }

                }
                else
                {
                    //Account not found
                    state.AddModelError("", Translations.ChangePassword_Failure);
                    return false;
                }
            }

            //Invalid request (no useraccountid or verification code provided)
            state.AddModelError("", Translations.ChangePassword_Failure);
            return false;
        }
    }
}
